package com.example.elasticsearchdemo.dao;

import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.util.Assert;

import java.util.Set;

public interface CommonElasticsearchOperations<T> {





    /**
     *
     * @param keyword           查询的关键字
     * @param queryFields       匹配的字段
     * @param page              页数.从1开始
     * @param pageSize          每页条目数
     * @param limitFields       限定的字段
     * @param highlightFields   高亮字段
     * @param preTag            高亮字段匹配关键字的前置标签
     * @param postTag           高亮字段匹配关键字的后置标签
     * @return                  查询结果
     */
    default Page<T> searchInPageHighlight(String keyword, Set<String> queryFields, int page, int pageSize, Set<String> limitFields, Set<String> highlightFields, String preTag, String postTag) {

        Assert.isTrue(page > 0, "页数从1开始");
        Assert.isTrue(pageSize > 0, "每页条目数必须大于0");
        Assert.isTrue(queryFields != null && queryFields.size() > 0, "无效查询");

        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();

        String[] ss;

        ss = new String[queryFields.size()];
        queryFields.toArray(ss);
        //全文查询无法将字段高亮
        builder.withQuery(QueryBuilders.multiMatchQuery(keyword, ss));

        //限定的字段
        if (limitFields != null && limitFields.size() > 0) {
            ss = new String[limitFields.size()];
            limitFields.toArray(ss);
            builder.withFields(ss);
        }

            //高亮的字段
        if (highlightFields != null && highlightFields.size() > 0) {
            Assert.isTrue(queryFields.containsAll(highlightFields), "高亮字段必须含于查询字段");
            HighlightBuilder.Field[] fields = new HighlightBuilder.Field[highlightFields.size()];
            ss = new String[highlightFields.size()];
            highlightFields.toArray(ss);
            if (preTag != null && postTag != null) {
                for (int i = 0; i < fields.length; i++) {
                    fields[i] = new HighlightBuilder.Field(ss[i]).preTags(preTag).postTags(postTag);
                }
            } else {
                for (int i = 0; i < fields.length; i++) {
                    fields[i] = new HighlightBuilder.Field(ss[i]);
                }
            }
            builder.withHighlightFields(fields);

        }

        builder.withPageable(PageRequest.of(page - 1, pageSize));

        return elasticsearchOperations().queryForPage(builder.build(), type(), ResultMapper.getInstance());
    }


    //采用默认的高亮标签
    default Page<T> searchInPageHighlight(String keyword, Set<String> queryFields, int page, int pageSize, Set<String> limitFields, Set<String> highlightFields) {
        return searchInPageHighlight(keyword, queryFields, page, pageSize, limitFields, highlightFields, null, null);
    }

    //采用默认高亮标签.无限定字段.
    default Page<T> searchInPageHighlight(String keyword, Set<String> queryFields, int page, int pageSize, Set<String> highlightFields) {
        return searchInPageHighlight(keyword, queryFields, page, pageSize, null, highlightFields);
    }

    //采用默认高亮标签.无限定字段.无高亮字段采用即查询字段
    default Page<T> searchInPageHighlight(String keyword, Set<String> queryFields, int page, int pageSize) {
        return searchInPageHighlight(keyword, queryFields, page, pageSize, queryFields);
    }


    //无限定字段但可以自定义前后置标签
    default Page<T> searchInPageHighlight(String keyword, Set<String> queryFields, int page, int pageSize, Set<String> highlightFields, String preTag, String postTag) {
        return searchInPageHighlight(keyword, queryFields, page, pageSize, null, highlightFields, preTag, postTag);
    }



    //无限定字段,将匹配字段高亮.并且自定义标签
    default Page<T> searchInPageHighlight(String keyword, Set<String> queryFields, int page, int pageSize, String preTag, String postTag) {
        return searchInPageHighlight(keyword, queryFields, page, pageSize, null, queryFields, preTag, postTag);
    }


    //有限定字段无高亮字段
    default Page<T> searchInPage(String keyword, Set<String> queryFields, int page, int pageSize,Set<String> limitFields) {
        return searchInPageHighlight(keyword, queryFields, page, pageSize, limitFields, null, null, null);
    }


    //无限定字段无高亮字段
    default Page<T> searchInPage(String keyword, Set<String> queryFields, int page, int pageSize) {
        return searchInPage(keyword, queryFields, page, pageSize, null);
    }




    ElasticsearchOperations elasticsearchOperations();

    Class<T> type();
}
